#nullable enable
using Microsoft.AspNetCore.Http;

namespace Application.Service.LogCache;

/// <summary>
/// Furion日志包装器 - 包装Furion的静态日志方法并写入缓存
/// 全局静态类，可在任何地方直接调用
/// </summary>
public static class LogWrapper
{
    private static LogCacheService? _logCacheService;
    private static readonly object _lockObject = new object();

    /// <summary>
    /// 获取日志缓存服务实例
    /// </summary>
    private static LogCacheService LogCacheService
    {
        get
        {
            if (_logCacheService == null)
            {
                lock (_lockObject)
                {
                    if (_logCacheService == null)
                    {
                        // 尝试从Furion的服务容器中获取实例
                        var serviceProvider = Furion.App.RootServices;
                        if (serviceProvider != null)
                        {
                            _logCacheService = serviceProvider.GetService<LogCacheService>();
                        }
                        
                        // 如果无法从容器获取，创建一个新的实例（仅用于测试或特殊情况）
                        _logCacheService ??= new LogCacheService();
                    }
                }
            }
            return _logCacheService;
        }
    }

    
    /// <summary>
    /// 初始化日志包装器（向后兼容，现在自动获取服务）
    /// </summary>
    /// <param name="logCacheService">日志缓存服务</param>
    public static void Initialize(LogCacheService logCacheService)
    {
        _logCacheService = logCacheService;
    }
    
    /// <summary>
    /// 清空日志缓存
    /// </summary>
    public static void Clear()
    {
        LogCacheService.Clear();
    }

    /// <summary>
    /// 写入跟踪级别日志
    /// </summary>
    public static void Trace(string message,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string filePath = "",
        [CallerLineNumber] int lineNumber = 0)
    {
        Log.Trace(message);
        InterceptLog(LogLevel.Trace, message, null, memberName, filePath, lineNumber);
    }

    /// <summary>
    /// 写入调试级别日志
    /// </summary>
    public static void Debug(string message, 
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string filePath = "",
        [CallerLineNumber] int lineNumber = 0)
    {
        Log.Debug(message);
        InterceptLog(LogLevel.Debug, message, null, memberName, filePath, lineNumber);
    }

    /// <summary>
    /// 写入信息级别日志
    /// </summary>
    public static void Information(string message, 
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string filePath = "",
        [CallerLineNumber] int lineNumber = 0)
    {
        Log.Information(message);
        InterceptLog(LogLevel.Information, message, null, memberName, filePath, lineNumber);
    }

    /// <summary>
    /// 写入信息级别日志（带参数）
    /// </summary>
    public static void Information(string message, params object[] args)
    {
        Log.Information(message, args);
        InterceptLog(LogLevel.Information, string.Format(message, args));
    }

    /// <summary>
    /// 写入警告级别日志
    /// </summary>
    public static void Warning(string message, 
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string filePath = "",
        [CallerLineNumber] int lineNumber = 0)
    {
        Log.Warning(message);
        InterceptLog(LogLevel.Warning, message, null, memberName, filePath, lineNumber);
    }

    /// <summary>
    /// 写入错误级别日志
    /// </summary>
    public static void Error(string message, 
        Exception? exception = null,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string filePath = "",
        [CallerLineNumber] int lineNumber = 0)
    {
        if (exception != null)
        {
            Log.Error(message, exception);
        }
        else
        {
            Log.Error(message);
        }
        InterceptLog(LogLevel.Error, message, exception, memberName, filePath, lineNumber);
    }

    /// <summary>
    /// 写入错误级别日志（带参数）
    /// </summary>
    public static void Error(string message, Exception? exception = null, params object[] args)
    {
        if (exception != null)
        {
            Log.Error(string.Format(message, args), exception);
        }
        else
        {
            Log.Error(string.Format(message, args));
        }
        InterceptLog(LogLevel.Error, string.Format(message, args), exception);
    }

    /// <summary>
    /// 写入严重级别日志
    /// </summary>
    public static void Critical(string message, 
        Exception? exception = null,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string filePath = "",
        [CallerLineNumber] int lineNumber = 0)
    {
        if (exception != null)
        {
            Log.Critical(message, exception);
        }
        else
        {
            Log.Critical(message);
        }
        InterceptLog(LogLevel.Critical, message, exception, memberName, filePath, lineNumber);
    }

    /// <summary>
    /// 拦截日志并写入缓存
    /// </summary>
    private static void InterceptLog(LogLevel level, string message, Exception? exception = null,
        string memberName = "", string filePath = "", int lineNumber = 0)
    {
        try
        {
            // 写入内存缓存
            LogCacheService?.AddLog(new LogEntry
            {
                Timestamp = DateTime.Now,
                Level = level,
                Message = message,
                Exception = exception,
                CallerMemberName=memberName,
                CallerFilePath=filePath,
                CallerLineNumber=lineNumber
                // CallerInfo = $"{memberName} at {filePath}:{lineNumber}"
            });

            // 异步写入数据库（不等待，避免阻塞）
            _ = WriteToDatabaseAsync(level, message, exception, memberName, filePath, lineNumber);
        }
        catch (Exception ex)
        {
            // 如果服务不可用，只记录到Furion日志
            Log.Error($"写入日志缓存失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 异步写入数据库
    /// </summary>
    private static async Task WriteToDatabaseAsync(LogLevel level, string message, Exception? exception, string callerMemberName, string callerFilePath, int callerLineNumber)
    {
        try
        {
            // 使用HttpContextAccessor获取当前请求的作用域服务
            var httpContextAccessor = App.RootServices.GetService<IHttpContextAccessor>();
            if (httpContextAccessor?.HttpContext?.RequestServices != null)
            {
                var systemLogService = httpContextAccessor.HttpContext.RequestServices.GetService<SystemLogService>();
                if (systemLogService != null)
                {
                    var log = new SystemLog
                    {
                        Level = level.ToString(),
                        Message = message,
                        Exception = exception?.ToString(),
                        CallerMemberName = callerMemberName,
                        CallerFilePath = callerFilePath,
                        CallerLineNumber = callerLineNumber,
                        CreateTime = DateTime.Now
                    };

                    await systemLogService.AddLogAsync(log);
                }
            }
        }
        catch (Exception ex)
        {
            // 数据库写入失败，只记录到Furion日志
            Log.Error($"写入数据库日志失败: {ex.Message}");
        }
    }
}
